#include <stdio.h>
#include <math.h>
#include "../app.h"
#include "../font/font.h"
#include "dvc.h"

typedef void (*afe_state_cb_t)(dvc_t, uint8_t, uint8_t);
typedef struct infos
{
    const char *const name;
    afe_state_cb_t cb;
    uint8_t disable : 1;
    uint8_t bit : 4;
} afe_states_t;

static const afe_states_t infos_map[] = {
    {"充电开关", .bit = 0, .cb = (afe_state_cb_t)dvc_chg},
    {"放电开关", .bit = 1, .cb = (afe_state_cb_t)dvc_dsg},
    {"主动均衡", .bit = 15, .cb = (afe_state_cb_t)dvc_aes},
    {"负载接入", .disable = 1, .bit = 14},
    {"放电过流", .disable = 1, .bit = 2},
    {"放电短路", .disable = 1, .bit = 3},
    {"电池欠压", .disable = 1, .bit = 4},
    {"电池过压", .disable = 1, .bit = 5},
    {"充电过流", .disable = 1, .bit = 6},
    {"触发警报", .disable = 1, .bit = 7},
    {"电流传感器", .disable = 1, .bit = 8},
    {"电压传感器", .disable = 1, .bit = 9},
};

#define AFE_INFOS_SIZE (sizeof(infos_map) / sizeof(infos_map[0]))

#define ERR_TEXT_COLOR lv_color_make(245, 108, 108)
#define Normal_TEXT_COLOR lv_color_make(64, 158, 255)

extern dvc_t gloab_dvc;
static int8_t cur_select = -1;

static void list_select_item(lv_obj_t *page, uint8_t id)
{
    lv_obj_t *list = lv_obj_get_child(page, 0);
    uint8_t cnt = lv_obj_get_child_cnt(list);
    for (uint8_t i = 0; i < cnt; i++)
    {
        lv_obj_t *cur_item = lv_obj_get_child(list, i);
        lv_obj_set_style_border_color(cur_item, lv_color_make(64, 64, 64), LV_PART_MAIN);
        lv_obj_set_style_text_color(cur_item, lv_color_make(255, 255, 255), LV_PART_MAIN);
    }
    lv_obj_t *item = lv_obj_get_child(list, id);
    if (!item)
        return;
    lv_obj_set_style_text_color(item, lv_color_make(255, 165, 2), LV_PART_MAIN);
    lv_obj_set_style_border_color(item, lv_color_make(255, 165, 2), LV_PART_MAIN);
    lv_obj_scroll_to_view(item, 1);
    cur_select = id;
}

static void timer_task_cb(struct _lv_timer_t *timer)
{
    if (!gloab_dvc)
        return;
    uint16_t status = ((*(uint16_t *)&gloab_dvc->status.status0) & 0x7FFF) | gloab_dvc->aes << 15;

    lv_obj_t *page = timer->user_data;
    lv_obj_t *list = lv_obj_get_child(page, 0);
    for (uint8_t i = 0; i < AFE_INFOS_SIZE; i++)
    {
        lv_obj_t *item = lv_obj_get_child(list, i);
        if (!infos_map[i].disable)
        {
            lv_obj_t *sw = lv_obj_get_child(item, 0);
            if ((status >> infos_map[i].bit) & 0x01) /* 开启 */
                lv_obj_add_state(sw, LV_STATE_CHECKED);
            else
                lv_obj_clear_state(sw, LV_STATE_CHECKED);
        }
        else
        {
            lv_obj_t *label = lv_obj_get_child(item, 0);
            bool err = (status >> infos_map[i].bit) & 0x01;
            if (i == 3)
                err = !(status >> infos_map[i].bit) & 0x01;
            if (err) /* 错误 */
            {
                lv_obj_set_style_bg_color(label, ERR_TEXT_COLOR, LV_PART_MAIN);
                lv_obj_set_style_text_color(label, ERR_TEXT_COLOR, LV_PART_MAIN);
                lv_label_set_text_static(label, "异常");
            }
            else
            {
                lv_obj_set_style_bg_color(label, Normal_TEXT_COLOR, LV_PART_MAIN);
                lv_obj_set_style_text_color(label, Normal_TEXT_COLOR, LV_PART_MAIN);
                lv_label_set_text_static(label, "正常");
            }
        }
    }
}

lv_timer_t *app_afe_state_create(lv_obj_t *parent, uint8_t id)
{
    if (!parent)
        return NULL;

    lv_obj_t *obj = lv_tileview_add_tile(parent, id, 0, LV_DIR_HOR);
    lv_obj_set_style_pad_all(obj, 10, LV_PART_MAIN);
    lv_obj_set_style_text_font(obj, base_font18, LV_PART_MAIN);
    lv_obj_set_style_bg_color(obj, lv_color_make(0, 0, 0), LV_PART_MAIN);

    lv_obj_t *list = lv_list_create(obj);
    lv_obj_set_size(list, LV_PCT(100), LV_PCT(100));
    lv_obj_set_style_radius(list, 0, LV_PART_MAIN);
    lv_obj_set_style_border_width(list, 0, LV_PART_MAIN);
    lv_obj_set_style_pad_row(list, 5, LV_PART_MAIN);
    lv_obj_set_flex_flow(list, LV_FLEX_FLOW_COLUMN);
    lv_obj_set_style_bg_color(list, lv_color_make(0, 0, 0), LV_PART_MAIN);
    lv_obj_set_style_bg_opa(list, LV_OPA_50, LV_PART_MAIN);
    lv_obj_set_scrollbar_mode(list, LV_SCROLLBAR_MODE_OFF);

    for (uint8_t i = 0; i < AFE_INFOS_SIZE; i++)
    {
        lv_obj_t *label = lv_list_add_text(list, infos_map[i].name);
        lv_obj_set_style_pad_ver(label, 5, LV_PART_MAIN);
        lv_obj_set_style_bg_color(label, lv_color_make(64, 64, 64), LV_PART_MAIN);
        lv_obj_set_style_text_color(label, lv_color_make(255, 255, 255), LV_PART_MAIN);
        lv_obj_set_style_border_color(label, lv_color_make(64, 64, 64), LV_PART_MAIN);
        lv_obj_set_style_border_width(label, 1, LV_PART_MAIN);
        if (!infos_map[i].disable)
        {
            lv_obj_t *sw = lv_switch_create(label);
            lv_obj_align(sw, LV_ALIGN_RIGHT_MID, -5, 0);
            lv_obj_add_state(sw, LV_STATE_CHECKED);
        }
        else
        {
            lv_obj_t *sub_label = lv_label_create(label);
            lv_obj_set_style_pad_all(sub_label, 5, LV_PART_MAIN);
            lv_obj_set_style_radius(sub_label, 5, LV_PART_MAIN);
            lv_obj_set_style_bg_opa(sub_label, LV_OPA_50, LV_PART_MAIN);
            lv_obj_set_style_bg_color(sub_label, Normal_TEXT_COLOR, LV_PART_MAIN);
            lv_obj_set_style_text_color(sub_label, Normal_TEXT_COLOR, LV_PART_MAIN);
            lv_label_set_text_static(sub_label, "正常");
            lv_obj_align(sub_label, LV_ALIGN_RIGHT_MID, -5, 0);
        }
    }

    lv_timer_t *timer = lv_timer_create(timer_task_cb, 250, obj);
    lv_timer_pause(timer);
    return timer;
}
uint8_t afe_state_update(lv_timer_t *timer, void *user_data, uint8_t event)
{
    lv_obj_t *page = timer->user_data;
    if (event == APP_EVENT_TYPE_NEXT)
    {
        if (cur_select == -1)
            return 0;
        uint8_t idx = cur_select + 1;
        if (idx >= AFE_INFOS_SIZE)
            idx = 0;
        if (idx != cur_select)
        {
            cur_select = idx;
            list_select_item(page, cur_select);
        }
        return 1;
    }
    else if (event == APP_EVENT_TYPE_CLICK)
    {
        if (cur_select == -1)
            return 0;
        if (!gloab_dvc)
            return 1;
        if (infos_map[cur_select].disable)
            return 1;
        lv_obj_t *list = lv_obj_get_child(page, 0);
        lv_obj_t *item = lv_obj_get_child(list, cur_select);
        lv_obj_t *sw = lv_obj_get_child(item, 0);
        uint8_t enable = 1;
        if (lv_obj_has_state(sw, LV_STATE_CHECKED))
        {
            lv_obj_clear_state(sw, LV_STATE_CHECKED);
            enable = 0;
        }
        else
            lv_obj_add_state(sw, LV_STATE_CHECKED);

        if (infos_map[cur_select].cb)
        {
            infos_map[cur_select].cb(gloab_dvc, enable, DVC_EVENT_FLAG_USER);
            dvc_config_commit(gloab_dvc);
        }
        return 1;
    }
    else if (event == APP_EVENT_TYPE_CONFIRM) /* 进入 / 退出页面 */
    {
        lv_obj_t *list = lv_obj_get_child(page, 0);
        if (cur_select != -1)
        {
            lv_obj_t *item = lv_obj_get_child(list, cur_select);
            lv_obj_set_style_text_color(item, lv_color_make(255, 255, 255), LV_PART_MAIN);
            lv_obj_set_style_border_color(item, lv_color_make(64, 64, 64), LV_PART_MAIN);
            lv_obj_set_scrollbar_mode(list, LV_SCROLLBAR_MODE_OFF);

            cur_select = -1;
            return 0;
        }
        else
        {
            lv_obj_set_scrollbar_mode(list, LV_SCROLLBAR_MODE_AUTO);
            list_select_item(timer->user_data, 0);
            return 1;
        }
        return 0;
    }
    return 0;
}

app_s afe_state_page = {
    .name = "afe_state",
    .create = app_afe_state_create,
    .delete = NULL,
    .enter = NULL,
    .level = NULL,
    .update = afe_state_update,
    .user_data = NULL,
};
